<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8" />
    <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Document</title>
    <style>
        * {
            margin: 0;
            padding: 0;
        }
        
        body {
            width: 1000px;
            height: 300px;
            margin: 0 auto;
            position: relative;
        }
        
        p {
            position: absolute;
            left: 50%;
            top: 40%;
        }
        
        ul {
            position: absolute;
            left: 50%;
            top: 50%;
        }
        
        button {
            position: absolute;
            left: 50%;
            top: 60%;
        }
        
        span {
            position: absolute;
            left: 60%;
            top: 60%;
        }
    </style>
</head>

<body>
    <!-- ES5新特性: -->
    <!-- forEach, map, filter, Object.create, Object.defineProperty -->
    <!-- ES与JS的关系 -->
    <!-- JS(浏览器端) = ES(语法+API) + DOM + BOM -->
    <!-- ES6新特性: -->
    <!-- 
      1.let,const块级作用域
      2.模板字符串使用反引号``${}  '我的名字是: '+ Person.name +''(字符串拼接) `我的名字是: ${Person.name}`(模板字符串拼接)
      (多行字符串输出,原方案\n,使用``可以直接回车
      输出`和\等特殊字符使用\
      模板字符串注入:
      const person = {username: 'aaa', age: 15, sex: 'male'}
      const getSex = function(sex) {
        return sex=='male'?'男':'女' 
      }
      console.log(`我是${getSex(person.sex)}的`)
      )
      3.箭头函数(匿名函数声明为常量或变量) =>
      4.解构赋值(解析数据结构,获取想要的数据)
      原理:1.模式(结构)匹配(左右结构相同), 2.索引值相同的完成赋值
      const [a, b, c] = [1, 2, 3]
     -->
    <p>学生信息表</p>
    <ul id="list">
        <li style="list-style: none">信息加载中....</li>
    </ul>

    <button id="btn">开始</button>
    <span id="number">1</span>
</body>
<script>
    const person = {
        username: "aaa",
        age: 15,
        sex: "male",
    };
    const students = [{
        username: "sss",
        age: 16,
        sex: "male",
    }, {
        username: "ccc",
        age: 17,
        sex: "male",
    }, {
        username: "cvv",
        age: 18,
        sex: "male",
    }, ];
    // 模板字符串的注入
    const getSex = function(sex) {
        return sex == "male" ? "男" : "女";
    };
    console.log(`我是${getSex(person.sex)}的`);
    // 模板字符串的应用
    const list = document.getElementById("list");
    let html = "";
    for (let i = 0; i < students.length; i++) {
        html += `我的名字是: ${students[i].username}`;
    }
    list.innerHTML = html;

    // 箭头函数的应用
    const btn = document.getElementById("btn");
    const number = document.getElementById("number");
    const timer = {
        time: 0,
        start: function() {
            console.log(this); //timer
            // 方案一,将timer对象提前保存
            var that = this;
            btn.addEventListener(
                "click",
                () => {
                    console.log(this); //button
                    setInterval(() => {
                        console.log(this); //window
                        this.time++;
                        number.innerHTML = this.time;
                    }, 1000);
                },
                false
            );
        },
    };
    timer.start();
    // 如果箭头函数返回单行对象,可以在{}外面加上()
    // this指向只和谁在调用有关系
    function add(x, y) {
        return x + y;
    }
    add(1, 3); // undefine => window(非严格模式下会转成window)
    // 构造函数中的this指向的是new后的实例
    const calc = {
        add: () => {
            console.log(this);
        },
        del: function() {
            console.log(this);
        },
    };
    calc.add(); // window, 对象是没有自己的this滴
    calc.del(); // calc,

    // 不适合箭头函数
    // 1.构造函数不适合使用
    // 2.需要this指向调用的时候(document绑定事件)
    // 3.需要使用arguments,可以使用剩余参数替代

    // 数组解构
    const [a, [, , b], c] = [1, [2, 4, 5], 3];
    console.log(a, b, c);

    // 1.默认值的基本用法
    const [d = 1, e = 2] = [];
    console.log(d, e);
    // 2.默认值的生效条件
    // 只有当一个数组成员严格等于(===)undefined时,对应的默认值才生效
    // const [f = 1, g = 1] = [3, null];
    // const [f = 1, g = 1] = [3, undefined];
    const [f = 1, g = 1] = [3];
    console.log(f, g);
    // 3.默认值表达式
    // 如果默认值是表达式,默认值表达式是惰性求值的
    const func = () => {
        console.log("我被执行了");
        return 1;
    };
    const [x = func()] = [];
    console.log(x);

    // 1.常见的类数组的解构赋值
    // arguments(类数组没有push,pop等方法,但是可以解构)
    function funca() {
        console.log(arguments);
    }
    funca();
    funca(1, 2);

    // 2.函数参数的解构赋值
    const array = [1, 2];
    // const addr = (arr) => arr[0] + arr[1];
    const addr = ([x = 0, y = 0]) => x + y; //相当于[x, y] = [1,2]
    console.log(addr(array));
    console.log(addr([]));
    // 3.交换变量
    let n = 1;
    let m = 2;
    [m, n] = [n, m];
    console.log(n, m);
    // 对象解构 {} = {}
    // 属性名相同的完成赋值(顺序无影响)
    const {
        username: name,
        age: old
    } = {
        username: "ddd",
        age: 16,
    };
    console.log(name, old);
    // 对象解构赋值的注意事项
    // 1.对象解构赋值的默认值
    // 默认值的生效条件：对象属性严格等于undefined时，对应的默认值才会生效,也是惰性求值
    const {
        username = "张三"
    } = {
        username: undefined,
    };
    console.log(username);

    // 2.将一个已经声明的变量用于解构赋值:使用()
    let p = 1;
    // ({
    //     p
    // } = {
    //     p: 1,
    // });
    [p] = [2];
    console.log(p);
    // 3.可以取到继承的属性
    const {
        toString
    } = {};
    const dict = {
        username: 33,
    };
    console.log(typeof dict.toString());
    console.log(Object.prototype);
    // toString与JSON.stringify
    var arr = [1, 2, 3];
    console.log(JSON.stringify(arr)); //'[1,2,3]'
    console.log(arr.toString()); //1,2,3

    // 对象解构赋值的应用
    // const logPersonInfo = (user) => console.log(user.username, user.age);
    const logPersonInfo = ({
            username = "刘敬叔",
            age = 0
        }) =>
        console.log(username, age);
    const logUser = (options = {}) => {
        // 添加默认值，传递undefined时可以转化为使用默认值
    };
</script>

</html>